#include <iostream>
#include <fstream>
using namespace std;

//基类
class Person
{
public:
	string number;//学号（编号）
	string name;//姓名
	string ID;//身份证号
	string sex;//性别
	string birthday;//出生日期
	string school;//学校
	virtual void Scanf() = 0;//输入信息
	virtual void Printf() = 0;//输出信息
	virtual void Save() = 0;//保存信息
};

//本科生
class Undergraduate:public Person
{
public:
	string grade;//年级
	string major;//专业
	string clas;//班级

	Undergraduate()
	{
		number = " ";
		name = " ";
		ID = " ";
		sex = ' ';
		birthday = " ";
		school = " ";
		grade = " ";
		major = " ";
		clas = " ";
	}

	void Scanf()
	{
		cout << "学号：";
		cin >> number;
		cout << "姓名：";
		cin >> name;
		cout << "身份证号：";
		cin >> ID;
		cout << "性别：";
		cin >> sex;
		cout << "出生日期：";
		cin >> birthday;
		cout << "在读学校：";
		cin >> school;
		cout << "年级：";
		cin >> grade;
		cout << "专业：";
		cin >> major;
		cout << "班级：";
		cin >> clas;
	}

	void Printf()
	{
		cout << "学号：" << number << endl;
		cout << "姓名：" << name << endl;
		cout << "身份证号：" << ID << endl;
		cout << "性别：" << sex << endl;
		cout << "出生日期：" << birthday << endl;
		cout << "在读学校：" << school << endl;
		cout << "年级：" << grade << endl;
		cout << "专业：" << major << endl;
		cout << "班级：" << clas << endl;
	}
	
	void Save()
	{
		ofstream outfile("本科生.txt",ios::app);
		outfile << number << "     \t";
		outfile << name << "     \t";
		outfile << ID << "     \t";
		outfile << sex << "     \t";
		outfile << birthday << "     \t";
		outfile << school << "     \t";
		outfile << grade << "     \t";
		outfile << major << "     \t";
		outfile << clas << endl;
	}
};

//研究生
class Graduate :public Person
{
public:
	string grade;//年级
	string major;//专业
	string clas;//班级
	string research;//研究方向
	string tutor;//导师姓名

	Graduate()
	{
		number = " ";
		name = " ";
		ID = " ";
		sex = ' ';
		birthday = " ";
		school = " ";
		grade = " ";
		major = " ";
		clas = " ";
		research = " ";
		tutor = " ";
	}

	void Scanf()
	{
		cout << "学号：";
		cin >> number;
		cout << "姓名：";
		cin >> name;
		cout << "身份证号：";
		cin >> ID;
		cout << "性别：";
		cin >> sex;
		cout << "出生日期：";
		cin >> birthday;
		cout << "在读学校：";
		cin >> school;
		cout << "年级：";
		cin >> grade;
		cout << "专业：";
		cin >> major;
		cout << "班级：";
		cin >> clas;
		cout << "研究方向：";
		cin >> research;
		cout << "导师姓名：";
		cin >> tutor;
	}

	void Printf()
	{
		cout << "学号：" << number << endl;
		cout << "姓名：" << name << endl;
		cout << "身份证号：" << ID << endl;
		cout << "性别：" << sex << endl;
		cout << "出生日期：" << birthday << endl;
		cout << "在读学校：" << school << endl;
		cout << "年级：" << grade << endl;
		cout << "专业：" << major << endl;
		cout << "班级：" << clas << endl;
		cout << "研究方向：" << research << endl;
		cout << "导师姓名：" << tutor << endl;
	}

	void Save()
	{
		ofstream outfile("研究生.txt", ios::app);
		outfile << number << "     \t";
		outfile << name << "     \t";
		outfile << ID << "     \t";
		outfile << sex << "     \t";
		outfile << birthday << "     \t";
		outfile << school << "     \t";
		outfile << grade << "     \t";
		outfile << major << "     \t";
		outfile << clas << "     \t";
		outfile << research << "     \t";
		outfile << tutor << endl;
	}
};

//教师
class Teacher:public Person
{
public:
	string department;//部门

	Teacher()
	{
		number = " ";
		name = " ";
		ID = " ";
		sex = ' ';
		birthday = " ";
		school = " ";
		department = " ";
	}

	void Scanf()
	{
		cout << "编号：";
		cin >> number;
		cout << "姓名：";
		cin >> name;
		cout << "身份证号：";
		cin >> ID;
		cout << "性别：";
		cin >> sex;
		cout << "出生日期：";
		cin >> birthday;
		cout << "所在学校：";
		cin >> school;
		cout << "所在部门：";
		cin >> department;
	}

	void Printf()
	{
		cout << "编号：" << number << endl;
		cout << "姓名：" << name << endl;
		cout << "身份证号：" << ID << endl;
		cout << "性别：" << sex << endl;
		cout << "出生日期：" << birthday << endl;
		cout << "所在学校：" << school << endl;
		cout << "所在部门：" << department << endl;
	}

	void Save()
	{
		ofstream outfile("教师.txt", ios::app);
		outfile << number << "     \t";
		outfile << name << "     \t";
		outfile << ID << "     \t";
		outfile << sex << "     \t";
		outfile << birthday << "     \t";
		outfile << school << "     \t";
		outfile << department << endl;
	}
};

template <typename T>//动态数组函数模板
void Change(T*& identity, int oldlength, int newlength)
{
	T* temp = new T[newlength];
	int number = min(oldlength, newlength);
	copy(identity, identity + number, temp); 
	delete[]identity;
	identity = temp;
}

template<typename T>//添加信息函数模板
void Get(T& identity, int& oldlength)
{
	int newlength = oldlength + 1;
	Change(identity, oldlength, newlength);
	identity[oldlength].Scanf();
	oldlength = newlength;
}

template<typename T>//删除信息函数模板
void Delete(T& identity, int& oldlength,int number)
{
	cout << endl;
	cout << ">>>>>>>>>>请确认是否删除<<<<<<<<<<" << endl;
	cout << "*            1、确定             *" << endl;
	cout << "*            2、返回             *" << endl;
	cout << "**********************************" << endl;
	cout << "请慎重选择，删除后无法恢复：";
	int choice;
	cin >> choice;;
	switch (choice)
	{
	case 1:
	{

		for (int x = number; x < oldlength - 1; x++)
		{

			identity[x] = identity[x + 1];
		}
		Change(identity, oldlength, oldlength - 1);
		oldlength = oldlength - 1;
		cout << "删除成功！" << endl;
		break;
	}
	case 0:
	{
		break;
	}
	default:
		break;
	}
}

template<typename T>//保存信息函数模板
void Preservation(T identity,int oldlength)
{
	for (int i = 0; i < oldlength; i++)
	{
		identity[i].Save();
	}
}

//统计本科生文本数据中本科生对象数
int Ugive()
{
	char c;
	int n = 0;
	ifstream uinfile("本科生.txt", ios::in);
	while (uinfile.get(c))
	{
		if (c == '\n')
			n++;
	}
	uinfile.close();
	return n;
}

//统计研究生文本数据中研究生对象数
int Ggive()
{
	char c;
	int n = 0;
	ifstream ginfile("研究生.txt", ios::in);
	while (ginfile.get(c))
	{
		if (c == '\n')
			n++;
	}
	ginfile.close();
	return n;
}

//统计教师文本数据中教师对象数
int Tgive()
{
	char c;
	int n = 0;
	ifstream tinfile("教师.txt", ios::in);
	while (tinfile.get(c))
	{
		if (c == '\n')
			n++;
	}
	tinfile.close();
	return n;
}

//主界面
void Interface()
{
	cout << ">>>>>>>>>>欢迎使用高校师生信息管理系统<<<<<<<<<<" << endl;
	cout << "************************************************" << endl;
	cout << "*                  1.添加信息                  *" << endl;
	cout << "*                  2.查找信息                  *" << endl;
	cout << "*                  3.修改信息                  *" << endl;
	cout << "*                  4.删除信息                  *" << endl;
	cout << "*                  5.保存信息                  *" << endl;
	cout << "*                  6.读取信息                  *" << endl;
	cout << "*                  0.退出                      *" << endl;
	cout << "************************************************" << endl;
	cout << "注意事项：①读取信息前请确保新添加的信息已保存" << endl;
	cout << "          ②退出前请确保所有信息已保存" << endl;
	cout << "          ③请添加完所有信息后再进行保存" << endl;
	cout << "          ④建议在退出前再进行保存" << endl;
	cout << "          ⑤保存信息的文本编码格式应为ANSI" << endl;
	cout << "请选择要执行的操作：";
}

//学生信息查询界面
void SInterface()
{
	cout << ">>>>>>>>>>查询方式<<<<<<<<<<" << endl;
	cout << "*         1、专业          *" << endl;
	cout << "*         2、班级          *" << endl;
	cout << "*         3、学号          *" << endl;
	cout << "****************************" << endl;
	cout << "请选择查询方式：";
}

//教师信息查询界面
void TInterface()
{
	cout << ">>>>>>>>>>查询方式<<<<<<<<<<" << endl;
	cout << "*         1、部门          *" << endl;
	cout << "*         2、编号          *" << endl;
	cout << "****************************" << endl;
	cout << "请选择查询方式：";
}

//主函数
int main()
{
	//初始化
	Undergraduate* U = new Undergraduate[1];//本科生对象数组
	int Uoldlength = 1;
	Graduate* G = new Graduate[1];//研究生对象数组
	int Goldlength = 1;
	Teacher* T = new Teacher[1];//教师对象数组
	int Toldlength = 1;
	//主程序
	while (1)
	{
		Interface();
		int choice;
		cin >> choice;
		switch (choice)
		{
		case 1://添加信息
		{
			cout << "所添加信息人员的身份（本科生/研究生/教师）：";
			string identity;
			cin >> identity;
			if (identity == "本科生")
			{
				Get(U, Uoldlength);
				cout << "添加本科生信息成功！" << endl;
			}
			else if (identity == "研究生")
			{
				Get(G, Goldlength);
				cout << "添加研究生信息成功！" << endl;
			}
			else if (identity == "教师")
			{
				Get(T, Toldlength);
				cout << "添加教师信息成功！" << endl;
			}
			cout << endl;
			////////////////////////////////////////////////////////////////////////////////////////////////////
			break;
		}
		case 2://查找信息
		{
			cout << "所查找信息人员的身份（学生/教师）：";
			string identity;
			cin >> identity;
			if (identity == "学生")
			{
				SInterface();
				int way;
				cin >> way;
				switch (way)
				{
				case 1:
				{
					cout << "所查找学生的专业：";
					string Fmajoy;
					cin >> Fmajoy;
					cout << endl;
					int n = 0;
					for (int i = 0; i < Uoldlength; i++)
					{
						if (U[i].major == Fmajoy)
						{
							U[i].Printf();
							n++;
							cout << endl;
						}
						else
							continue;
					}
					for (int j = 0; j < Goldlength; j++)
					{
						if (G[j].major == Fmajoy)
						{
							G[j].Printf();
							n++;
							cout << endl;
						}
						else
							continue;
					}
					if (n == 0)
					{
						cout << "查无此专业或此专业无人" << endl;
					}
					else
						cout << "本专业人数：" << n << endl;
					break;
				}
				case 2:
				{
					cout << "所查找学生的班级：";
					string Fclas;
					cin >> Fclas;
					cout << endl;
					int n = 0;
					for (int i = 0; i < Uoldlength; i++)
					{
						if (U[i].clas == Fclas)
						{
							U[i].Printf();
							n++;
							cout << endl;
						}
						else
							continue;
					}
					if (n == 0)
					{
						for (int j = 0; j < Goldlength; j++)
						{
							if (G[j].clas == Fclas)
							{
								G[j].Printf();
								n++;
								cout << endl;
							}
							else
								continue;
						}
					}
					if (n == 0)
					{
						cout << "查无此班级或此班级无人" << endl;
					}
					else
						cout << "本班级人数：" << n << endl;
					break;
				}
				case 3:
				{
					cout << "所查找学生的学号：";
					string Fnumber;
					cin >> Fnumber;
					cout << endl;
					int n = 0;
					for (int i = 0; i < Uoldlength; i++)
					{
						if (U[i].number == Fnumber)
						{
							U[i].Printf();
							cout << endl;
							n = 1;
							break;
						}
						else
							continue;
					}
					if (n == 0)
					{
						for (int j = 0; j < Goldlength; j++)
						{
							if (G[j].number == Fnumber)
							{
								G[j].Printf();
								cout << endl;
								n = 1;
								break;
							}
							else
								continue;
						}
					}
					if (n == 0)
					{
						cout << "查无此学生或输入的学生学号错误" << endl;
					}
					break;
				}
				default:
					break;
				}
			}
			else if (identity == "教师")
			{
			TInterface();
			int way;
			cin >> way;
			switch (way)
			{
			case 1:
			{
				cout << "所查找教师的部门：";
				string Fdepartment;
				cin >> Fdepartment;
				cout << endl;
				int n = 0;
				for (int i = 0; i < Toldlength; i++)
				{
					if (T[i].department == Fdepartment)
					{
						T[i].Printf();
						n++;
						cout << endl;
					}
					else
						continue;
				}
				if (n == 0)
				{
					cout << "查无此部门或此部门无人" << endl;
				}
				else
					cout << "本部门人数：" << n << endl;
				break;
			}
			case 2:
			{
				cout << "所查找教师的编号：";
				string Fnumber;
				cin >> Fnumber;
				cout << endl;
				int n = 0;
				for (int i = 0; i < Toldlength; i++)
				{
					if (T[i].number == Fnumber)
					{
						T[i].Printf();
						cout << endl;
						n = 1;
						break;
					}
					else
						continue;
				}
				if (n == 0)
				{
					cout << "查无此教师或输入的教师编号错误" << endl;
				}
				break;
			}
			default:
				break;
			}
            }
			cout << endl;
			////////////////////////////////////////////////////////////////////////////////////////////////////
            break;
		}
		case 3://修改信息
		{
			cout << "所修改信息人员的身份（学生/教师）：";
			string identity;
			cin >> identity;
			if (identity == "学生")
			{
				cout << "请输入所修改学生的学号：";
				string Fnumber;
				cin >> Fnumber;
				cout << endl;
				int n = 0;
				for (int i = 0; i < Uoldlength; i++)
				{
					if (U[i].number == Fnumber)
					{
						cout << "开始修改信息" << endl;
						U[i].Scanf();
						cout <<"修改信息成功！"<< endl;
						n = 1;
						break;
					}
					else
						continue;
				}
				if (n == 0)
				{
					for (int j = 0; j < Goldlength; j++)
					{
						if (G[j].number == Fnumber)
						{
							cout << "开始修改信息" << endl;
							G[j].Scanf();
							cout << "修改信息成功！" << endl;
							n = 1;
							break;
						}
						else
							continue;
					}
				}
				if (n == 0)
				{
					cout << "无此学生或输入的学生学号错误" << endl;
				}
			}
			else if (identity == "教师")
			{
				cout << "请输入所修改教师的编号：";
				string Fnumber;
				cin >> Fnumber;
				cout << endl;
				int n = 0;
				for (int i = 0; i < Toldlength; i++)
				{
					if (T[i].number == Fnumber)
					{
						cout << "开始修改信息" << endl;
						T[i].Scanf();
						cout << "修改信息成功！" << endl;
						n = 1;
						break;
					}
					else
						continue;
				}
				if (n == 0)
				{
					cout << "无此教师或输入的教师编号错误" << endl;
				}
			}
			cout << endl;
			////////////////////////////////////////////////////////////////////////////////////////////////////
			break;
		}
		case 4://删除信息
		{
			cout << "所删除信息人员的身份（学生/教师）：";
			string identity;
			cin >> identity;
			if (identity == "学生")
			{
				cout << "请输入所删除学生的学号：";
				string Fnumber;
				cin >> Fnumber;
				int n = NULL;
				int m = NULL;
				for (int i = 0; i < Uoldlength; i++)
				{
					if (U[i].number == Fnumber)
					{
						n = i;
						break;
					}
					else
						continue;
				}
				if (n == NULL)
				{
					for (int j = 0; j < Goldlength; j++)
					{
						if (G[j].number == Fnumber)
						{
							m = j;
							break;
						}
						else
							continue;
					}
				}
				if (n != NULL && m == NULL)
				{
					Delete(U, Uoldlength, n);
				}
				else if (n == NULL && m != NULL)
				{
					Delete(G, Goldlength, m);
				}
				else if (n == NULL && m == NULL)
				{
					cout << "无此学生或输入的学生学号错误" << endl;
				}
			}
			else if (identity == "教师")
			{
				cout << "请输入所删除教师的编号：";
				string Fnumber;
				cin >> Fnumber;
				int n = NULL;
				for (int i = 0; i < Toldlength; i++)
				{
					if (T[i].number == Fnumber)
					{
						n = i;
						break;
					}
					else
						continue;
				}
				if (n != NULL)
				{
					Delete(T, Toldlength, n);			
				}
				else
				{
					cout << "无此教师或输入的教师编号错误" << endl;
				}
			}
			cout << endl;
			////////////////////////////////////////////////////////////////////////////////////////////////////
			break;
		}
		case 5://保存信息
		{
			Preservation(U, Uoldlength);//保存本科生信息
			Preservation(G, Goldlength);//保存研究生信息
			Preservation(T, Toldlength);//保存教师信息
			cout << "保存信息成功！" << endl;
			cout << endl;
			////////////////////////////////////////////////////////////////////////////////////////////////////
			break;
		}
		case 6://读取信息
		{
			//读取本科生信息
			ifstream Uinfile("本科生.txt", ios::in);
			int Un = Ugive();
			string** u = new string* [Un];
			for (int i = 0; i < Un; i++)
			{
				u[i] = new string[9];
			}
			for (int i = 0; i < Un; i++)
			{
				int newlength = Uoldlength + 1;
				Change(U, Uoldlength, newlength);
				Uoldlength = newlength;
				for (int j = 0; j < 9; j++)
				{
					Uinfile >>u[i][j];
					if (j == 0)
					{
						U[i].number = u[i][j];
					}
					if (j == 1)
					{
						U[i].name = u[i][j];
					}
					if (j == 2)
					{
						U[i].ID = u[i][j];
					}
					if (j == 3)
					{
						U[i].sex = u[i][j];
					}
					if (j == 4)
					{
						U[i].birthday = u[i][j];
					}
					if (j == 5)
					{
						U[i].school = u[i][j];
					}
					if (j == 6)
					{
						U[i].grade = u[i][j];
					}
					if (j == 7)
					{
						U[i].major = u[i][j];
					}
					if (j == 8)
					{
						U[i].clas = u[i][j];
					}
				}
			}
			Uinfile.close();
			ofstream Uoutfile("本科生.txt");
			Uoutfile.close();
			//读取研究生信息
			ifstream Ginfile("研究生.txt", ios::in);
			int Gn = Ggive();
			string** g = new string * [Gn];
			for (int i = 0; i < Gn; i++)
			{
				g[i] = new string[11];
			}
			for (int i = 0; i < Gn; i++)
			{
				int newlength = Goldlength + 1;
				Change(G, Goldlength, newlength);
				Goldlength = newlength;
				for (int j = 0; j < 11; j++)
				{
					Ginfile >> g[i][j];
					if (j == 0)
					{
						G[i].number = g[i][j];
					}
					if (j == 1)
					{
						G[i].name = g[i][j];
					}
					if (j == 2)
					{
						G[i].ID = g[i][j];
					}
					if (j == 3)
					{
						G[i].sex = g[i][j];
					}
					if (j == 4)
					{
						G[i].birthday = g[i][j];
					}
					if (j == 5)
					{
						G[i].school = g[i][j];
					}
					if (j == 6)
					{
						G[i].grade = g[i][j];
					}
					if (j == 7)
					{
						G[i].major = g[i][j];
					}
					if (j == 8)
					{
						G[i].clas = g[i][j];
					}
					if (j == 9)
					{
						G[i].research = g[i][j];
					}
					if (j == 10)
					{
						G[i].tutor = g[i][j];
					}
				}
			}
			Ginfile.close();
			ofstream Goutfile("研究生.txt");
			Goutfile.close();
			//读取教师信息
			ifstream Tinfile("教师.txt", ios::in);
			int Tn = Tgive();
			string** t = new string * [Tn];
			for (int i = 0; i < Tn; i++)
			{
				t[i] = new string[7];
			}
			for (int i = 0; i < Tn; i++)
			{
				int newlength = Toldlength + 1;
				Change(T, Toldlength, newlength);
				Toldlength = newlength;
				for (int j = 0; j < 7; j++)
				{
					Tinfile >> t[i][j];
					if (j == 0)
					{
						T[i].number = t[i][j];
					}
					if (j == 1)
					{
						T[i].name = t[i][j];
					}
					if (j == 2)
					{
						T[i].ID = t[i][j];
					}
					if (j == 3)
					{
						T[i].sex = t[i][j];
					}
					if (j == 4)
					{
						T[i].birthday = t[i][j];
					}
					if (j == 5)
					{
						T[i].school = t[i][j];
					}
					if (j == 6)
					{
						T[i].department = t[i][j];
					}
				}
			}
			Tinfile.close();
			ofstream Toutfile("教师.txt");
			Toutfile.close();
			cout << "读取信息成功！" << endl;
			cout << endl;
			////////////////////////////////////////////////////////////////////////////////////////////////////
			break;
		}
		case 0://退出
		{
			cout << "欢迎下次使用！" << endl;
			exit(0);
		}
		default:
			break;
		}
	}
	return 0;
}